package mdt.figure;

import org.tigris.gef.base.Globals;
import org.tigris.gef.presentation.Fig;
import org.tigris.gef.presentation.FigNode;
import org.tigris.gef.presentation.Handle;

import java.awt.*;
import java.awt.event.KeyEvent;
import java.util.List;
import java.util.logging.Logger;

class SelectionMessage extends SelectionRerouteEdge {

	int fx;
	int fy;
	int fw;
	int fh;
	static final int LOCAL_HANDLE_BASE = 10;
	/**
	 * Logger.
	 */
	private static final Logger LOG = Logger.getLogger(SelectionMessage.class.getName());

	/**
	 * The constructor.
	 *
	 * @param feme
	 *          the fig.
	 */
	public SelectionMessage(FigMessage feme) {
		super(feme);
	}

	public void paint(Graphics g) {
		super.paint(g);
		g.setColor(Globals.getPrefs().handleColorFor(getContent()));
		updateInnerFigHandle();

		g.fillRect(fx - HAND_SIZE / 2, fy - HAND_SIZE / 2, HAND_SIZE,
				HAND_SIZE);
		g.fillRect(fx + fw - HAND_SIZE / 2, fy - HAND_SIZE / 2, HAND_SIZE,
				HAND_SIZE);
		g.fillRect(fx - HAND_SIZE / 2, fy + fh - HAND_SIZE / 2, HAND_SIZE,
				HAND_SIZE);
		g.fillRect(fx + fw - HAND_SIZE / 2, fy + fh - HAND_SIZE / 2,
				HAND_SIZE, HAND_SIZE);
	}

	protected void updateInnerFigHandle() {
		Rectangle rect = ((FigMessage)getContent()).getFigText().getBounds();
		fx = rect.x;
		fy = rect.y;
		fw = rect.width;
		fh = rect.height;
	}


	public void hitHandle(Rectangle r, Handle h) {
		super.hitHandle(r, h);
		if (h.index == -1) {
			updateInnerFigHandle();
			Rectangle testRect = new Rectangle(0, 0, 0, 0);
			testRect.setBounds(fx - HAND_SIZE / 2, fy - HAND_SIZE / 2,
					HAND_SIZE, fh + HAND_SIZE / 2);
			boolean leftEdge = r.intersects(testRect);
			testRect.setBounds(fx + fw - HAND_SIZE / 2, fy - HAND_SIZE / 2,
					HAND_SIZE, fh + HAND_SIZE / 2);
			boolean rightEdge = r.intersects(testRect);
			testRect.setBounds(fx - HAND_SIZE / 2, fy - HAND_SIZE / 2, fw
					+ HAND_SIZE / 2, HAND_SIZE);
			boolean topEdge = r.intersects(testRect);
			testRect.setBounds(fx - HAND_SIZE / 2, fy + fh - HAND_SIZE / 2, fw
					+ HAND_SIZE / 2, HAND_SIZE);
			boolean bottomEdge = r.intersects(testRect);
			// needs-more-work: midpoints for side handles
			if (leftEdge && topEdge) {
				h.index = LOCAL_HANDLE_BASE + Handle.NORTHWEST;
				//h.instructions = "Resize top left";
			} else if (rightEdge && topEdge) {
				h.index = LOCAL_HANDLE_BASE + Handle.NORTHEAST;
				//h.instructions = "Resize top right";
			} else if (leftEdge && bottomEdge) {
				h.index = LOCAL_HANDLE_BASE + Handle.SOUTHWEST;
				//h.instructions = "Resize bottom left";
			} else if (rightEdge && bottomEdge) {
				h.index = LOCAL_HANDLE_BASE + Handle.SOUTHEAST;
				//h.instructions = "Resize bottom right";
			}
		}
	}

	public void dragHandle(int mX, int mY, int anX, int anY, Handle hand) {
		if (hand.index < LOCAL_HANDLE_BASE) {
			super.dragHandle(mX, mY, anX, anY, hand);
			handleMovement();
			return;
		}

		hand.index -= LOCAL_HANDLE_BASE;

		final Fig figText = ((FigMessage)getContent()).getFigText();
		updateInnerFigHandle();

		final int x = fx;
		final int y = fy;
		final int w = fw;
		final int h = fh;
		int newX = x, newY = y, newWidth = w, newHeight = h;
		Dimension minSize = figText.getMinimumSize();
		int minWidth = minSize.width, minHeight = minSize.height;
		switch (hand.index) {
			case Handle.NORTHWEST:
				newWidth = x + w - mX;
				newWidth = (newWidth < minWidth) ? minWidth : newWidth;
				newHeight = y + h - mY;
				newHeight = (newHeight < minHeight) ? minHeight : newHeight;
				newX = x + w - newWidth;
				newY = y + h - newHeight;
				figText.setHandleBox(newX, newY, newWidth, newHeight);
				break;
			case Handle.NORTHEAST:
				newWidth = mX - x;
				newWidth = (newWidth < minWidth) ? minWidth : newWidth;
				newHeight = y + h - mY;
				newHeight = (newHeight < minHeight) ? minHeight : newHeight;
				newY = y + h - newHeight;
				figText.setHandleBox(newX, newY, newWidth, newHeight);
				break;
			case Handle.SOUTHWEST:
				newWidth = x + w - mX;
				newWidth = (newWidth < minWidth) ? minWidth : newWidth;
				newHeight = mY - y;
				newHeight = (newHeight < minHeight) ? minHeight : newHeight;
				newX = x + w - newWidth;
				figText.setHandleBox(newX, newY, newWidth, newHeight);
				break;
			case Handle.SOUTHEAST:
				newWidth = mX - x;
				newWidth = (newWidth < minWidth) ? minWidth : newWidth;
				newHeight = mY - y;
				newHeight = (newHeight < minHeight) ? minHeight : newHeight;

				figText.setHandleBox(newX, newY, newWidth, newHeight);
				break;
		}
		hand.index += LOCAL_HANDLE_BASE;
	}

	@Override
	public void keyPressed(KeyEvent ke) {
		if (ke.getKeyCode() == KeyEvent.VK_LEFT || ke.getKeyCode() == KeyEvent.VK_RIGHT) {
			// we don't let the user move the messages horizontally.
			ke.consume();
		} else {
			handleMovement();
		}
	}

	private void handleMovement() {
		FigMessage figMessage = (FigMessage) getContent();
		FigNode source = (FigNode) figMessage.getSourceFigNode();
		FigNode dest = (FigNode) figMessage.getDestFigNode();

		// if the edge is near the bottom of the classifier roles,
		// we enlarge all the FigNetworkDevices in the diagram.
		FigNode checkNode = null;
		if (source instanceof FigNetworkDevice) {
			checkNode = source;
		} else if (dest instanceof FigNetworkDevice) {
			checkNode = dest;
		}

		if (checkNode != null && figMessage.getFinalY() > checkNode.getY() + checkNode.getHeight() - 10) {
			final int newHeight = checkNode.getHeight() + 10;
			final List<Fig> figs = getContent().getLayer().getContents();

			for (Fig workOnFig : figs) {
				if (workOnFig instanceof FigNetworkDevice) {
					//enlarge only, never shrink
					int height = workOnFig.getHeight();
					if (newHeight > height)
						workOnFig.setHeight(newHeight);
				}
			}
		}

		//dest.positionHead(figMessage);
	}

}
